package factorytest.iflytek.com.einkiflytekfactorytest;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.os.Bundle;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;

import com.htfyun.eink.EinkUtils;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import factorytest.iflytek.com.einkiflytekfactorytest.common.BatteryCurrentThresholdEnum;
import factorytest.iflytek.com.einkiflytekfactorytest.common.BatteryInfo;
import factorytest.iflytek.com.einkiflytekfactorytest.common.LedCtrl;
import factorytest.iflytek.com.einkiflytekfactorytest.common.PermissionManager;
import factorytest.iflytek.com.einkiflytekfactorytest.common.SettingsUtils;
import factorytest.iflytek.com.einkiflytekfactorytest.config.EinkProperty;
import factorytest.iflytek.com.einkiflytekfactorytest.config.HtfyunBuildConfig;
import factorytest.iflytek.com.einkiflytekfactorytest.config.OTATestConfig;
import factorytest.iflytek.com.einkiflytekfactorytest.config.PCCommand;
import factorytest.iflytek.com.einkiflytekfactorytest.device.DeviceAttr;
import factorytest.iflytek.com.einkiflytekfactorytest.engineer_test.EngineerActivity;
import factorytest.iflytek.com.einkiflytekfactorytest.factorytestui.DspTestActivity;
import factorytest.iflytek.com.einkiflytekfactorytest.factorytestui.FactoryEinkScreenCalibActivity;
import factorytest.iflytek.com.einkiflytekfactorytest.factorytestui.FactoryTestItemsEnum;
import factorytest.iflytek.com.einkiflytekfactorytest.factorytestui.IFactoryTestItemSetListener;
import factorytest.iflytek.com.einkiflytekfactorytest.factorytestui.NvromTestActivity;
import factorytest.iflytek.com.einkiflytekfactorytest.utils.DebugLog;
import factorytest.iflytek.com.einkiflytekfactorytest.common.FTUtils;
import factorytest.iflytek.com.einkiflytekfactorytest.utils.UsefulUtils;


public class MainActivity extends FullScreenBaseActivity implements AdapterView.OnItemClickListener, View.OnClickListener{

    private final static String TAG = "MainActivity";
    private GridView gridlist;
    private List<FactoryTestItemsEnum> itemsEnumList = new ArrayList<>();

    private Context mContext;
    private TextView txtDesc;
    private TextView txtAgingResult;

    private Button btnCalib;

    private TextView txtBatteryInfo;
    private TextView txtPCBAInfo;
    private TextView txtSdcardInfo;
    private TextView txtOta;

    private MyGridAdapter myGridAdapter;

    private BatteryInfo batteryInfo;

    private MyHandler myHandler;

    private boolean isPause = false;

    private View btnOtaTest;

    //尝试解决: 多次调用 startActivityForResult 后, 会产生多个activity实例问题
    private SparseArray<Boolean> startActivityForResultMap = new SparseArray<>();


    @SuppressLint("StringFormatInvalid")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //不要一直亮屏
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        SettingsUtils.setScreenOffTimeForFT(this);

        setContentView(R.layout.activity_main_factory_test);

        mContext = this;

        myHandler = new MyHandler(this);

        batteryInfo = new BatteryInfo(this);

        btnCalib = (Button) findViewById(R.id.btnCalib);
        if (btnCalib != null) {
            btnCalib.setTag(FactoryEinkScreenCalibActivity.class);
            btnCalib.setOnClickListener(this);
        }

        View btnEmmc = findViewById(R.id.btnEmmcTest);
        if (btnEmmc != null) {
            btnEmmc.setTag(EmmcTestActivity.class);
            btnEmmc.setOnClickListener(this);
        }

        View btnCpu = findViewById(R.id.btnCpuTest);
        if (btnCpu != null) {
            btnCpu.setTag(CpuTestActivity.class);
            btnCpu.setOnClickListener(this);
        }
        View btnEngineerTest = findViewById(R.id.btnEngineerTest);
        if (btnEngineerTest != null) {
            btnEngineerTest.setTag(EngineerActivity.class);
            btnEngineerTest.setOnClickListener(this);
        }

        btnOtaTest = findViewById(R.id.btnOtaTest);
        if (btnOtaTest != null) {
            btnOtaTest.setTag(OTATestActivity.class);
//            btnOtaTest.setTag(NvromTestActivity.class);
            btnOtaTest.setOnClickListener(this);
        }

        gridlist = (GridView) findViewById(R.id.grid_list);
        gridlist.setOnItemClickListener(this);

        itemsEnumList.clear();

        myGridAdapter = new MyGridAdapter(mContext, -1, itemsEnumList);
        gridlist.setAdapter(myGridAdapter);

        txtDesc = (TextView) findViewById(R.id.txtDesc);
        txtAgingResult = (TextView) findViewById(R.id.txtAgingResult);

        TextView txtVersion = (TextView) findViewById(R.id.txtVersion);
        txtVersion.setText(getString(R.string.app_version, UsefulUtils.getAppVersion(mContext) + "-" + BuildConfig.BUILD_TYPE));

        TextView txtSerialno = (TextView) findViewById(R.id.txtSerialno);
        txtSerialno.setText(getString(R.string.serialno, EinkProperty.getSerialNumber()));

        TextView txtProductVersion = (TextView) findViewById(R.id.txtProductVersion);
        txtProductVersion.setText(getString(R.string.firmware_version, EinkProperty.getProductVersion()));

        DebugLog.e("app_version = " + txtVersion.getText());
        DebugLog.e("serialno = " + txtSerialno.getText());
        DebugLog.e("firmware_version = " + txtProductVersion.getText());

        TextView ram = (TextView) findViewById(R.id.txtRam);
        String ramString = getString(R.string.ram_test_result, UsefulUtils.getRamNominalSize(), getRamResult());
        ram.setText(getSpannableString(ramString));


        TextView rom = (TextView) findViewById(R.id.txtRom);
        String romString = getString(R.string.rom_test_result, UsefulUtils.getRomNominalSize(), getRomResult());
        rom.setText(getSpannableString(romString));

        txtBatteryInfo = (TextView) findViewById(R.id.txtBatteryInfo);
        txtPCBAInfo = (TextView) findViewById(R.id.txtPCBAInfo);

        txtOta = (TextView) findViewById(R.id.txtOta);

        txtSdcardInfo = (TextView) findViewById(R.id.txtSdcardInfo);

        if (!DeviceAttr.getRunningDeviceAttr().hasTFCard()) {
            txtSdcardInfo.setVisibility(View.GONE);
        } else {
            txtSdcardInfo.setVisibility(View.VISIBLE);
            updateUIWhileSDCardMounted();
        }

        registerSdcardReceiver();

        updateItemByAfterAging(true);

        FTUtils.startFTFloat(this);


        initAllPermission();

        FactoryTestItemsEnum.addItemSetListener(itemSetListener);

        startActivityForResultMap.clear();
    }

    private void updateOTATxt() {

        if (OTATestConfig.isEssentialForOTATest(mContext)) {

            String pass = getString(R.string.test_result_pass);
            String fail = getString(R.string.test_result_fail);

            if (OTATestConfig.isOTAStarted(mContext)) {
                OTATestConfig.setOTAStarted(mContext, false);
                boolean isUpgrade = EinkUtils.isOTAUpgrade(mContext);
                FactoryTestItemsEnum.ota.setResult(mContext, isUpgrade ? pass : fail);
                OTATestConfig.setOTAPassed(mContext, isUpgrade);
            }

            boolean isOTAPassed = FactoryTestItemsEnum.ota.isPassed(mContext);
            String result = getString(R.string.ota_test_result, isOTAPassed ? pass : fail);
            txtOta.setText(getSpannableString(result));

            txtOta.setVisibility(View.VISIBLE);

        } else {

            txtOta.setVisibility(View.GONE);

        }
    }

    private IFactoryTestItemSetListener itemSetListener = new IFactoryTestItemSetListener() {
        @Override
        public void onItemSet(String key, String result) {
            EinkProperty.setEinkFTTestAllResultPassed(FTUtils.isFTPassed());
        }
    };

    private String getRamResult() {
        BigDecimal definedRamSize = new BigDecimal(UsefulUtils.getDefinedRamSize());
        BigDecimal realRamSize = new BigDecimal(UsefulUtils.getRamTotalSize());
        String result = getString(realRamSize.compareTo(definedRamSize) > 0 ? R.string.test_result_pass : R.string.test_result_fail);
        FactoryTestItemsEnum.ram.setResult(mContext, result);
        return result;
    }

    private String getRomResult() {
        BigDecimal definedRomSize = new BigDecimal(UsefulUtils.getDefinedRomSize());
        BigDecimal realRomSize = new BigDecimal(UsefulUtils.getRomTotalSize());
        String result = getString(realRomSize.compareTo(definedRomSize) > 0 ? R.string.test_result_pass : R.string.test_result_fail);
        FactoryTestItemsEnum.rom.setResult(mContext, result);
        return result;
    }

    @Override
    protected void onResume() {
        super.onResume();
        DebugLog.e("onResume");

        updateOTATxt();

        String infoString = mContext.getString(R.string.pcba_test_result, FactoryTestItemsEnum.pcba.getResult(mContext));
        txtPCBAInfo.setText(getSpannableString(infoString));

        isPause = false;

        batteryInfo.setOnBatteryChangedListener(onBatteryChangedListener);
        batteryInfo.startMonitor();

        if (FTUtils.isInAgingTest(mContext)) {

            DebugLog.e("start aging test activity.");
            FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.aging;
            Intent intent = new Intent(mContext, itemsEnum.getItemClass());
            startActivityForResult(intent, itemsEnum.getIdentify());

        } else if (HtfyunBuildConfig.TEST_AGING_WITHOUT_SCREEN) {

            myHandler.sendEmptyMessageDelayed(MyHandler.MSG_CHECK_AGING, MyHandler.DELAY_CHECK_AGING);

        }

        if (PCCommand.isFromPCBroadcast(mContext)) {
            PCCommand.clearFromPCBroadcast(mContext);
        }

        updateMainUI();

        startLedCtrl();


        if (FactoryTestItemsEnum.pcba.isPassed(mContext)) {
            FTFloatWindowService.setPCBABtnShow(false);
        }
    }

    private void checkIfStartAging() {
        if (!FactoryTestItemsEnum.aging.isPassed(this)) {
            DebugLog.e("start aging test activity.");
            FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.aging;
            Intent intent = new Intent(mContext, itemsEnum.getItemClass());
            startActivityForResult(intent, itemsEnum.getIdentify());
        }
    }


    @Override
    protected void onPause() {
        super.onPause();
        DebugLog.e("onPause");

        isPause = true;

        batteryInfo.setOnBatteryChangedListener(null);
        batteryInfo.stopMonitor();

        stopLedCtrl();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        DebugLog.e("onDestroy");

        unregisterSdcardReceiver();

        FactoryTestItemsEnum.removeItemSetListener(itemSetListener);

        startActivityForResultMap.clear();
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {

        if (requestCode != REQUEST_CODE_USING_BTN) {
            Boolean started = startActivityForResultMap.get(requestCode);
            if ( started != null && started) {
                return;
            }

            startActivityForResultMap.put(requestCode, true);
        }

        DebugLog.e("startActivityForResult, requestCode = " + requestCode + ", intent = " + intent);

        super.startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        DebugLog.e( "onActivityResult requestCode = " + requestCode + ", resultCode = " + resultCode);

        startActivityForResultMap.remove(requestCode);

        FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.getItemEnumByIdentify(requestCode);

        if (itemsEnum == null) {
            return;
        }
        String result = getString(R.string.test_result_unknown);
        if (resultCode == RESULT_OK) {
            result = getString(R.string.test_result_pass);
        } else if (resultCode == RESULT_CANCELED) {
            result = getString(R.string.test_result_fail);
        }

        FactoryTestItemsEnum agingItemsEnum = FactoryTestItemsEnum.aging;

        DebugLog.e("itemsEnum = " + (itemsEnum));

        if (itemsEnum != agingItemsEnum && agingItemsEnum.isPassed(mContext)) {

            itemsEnum.setResultForAfterAging(mContext, result);

        } else {

            itemsEnum.setResult(mContext, result);

        }

        if (agingItemsEnum == itemsEnum) {
            itemsEnum.setResultForLog(mContext, FTUtils.getAgingResultInfo(mContext));

        }

        updateMainUI();

    }

    private boolean isAllGotPermission() {
        return !((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
        );
    }

    private void initAllPermission() {

        if (isAllGotPermission()) {
            return;
        }

        //同时申请多个权限
        PermissionManager.getInstance(getApplicationContext()).execute(this,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                android.Manifest.permission.RECORD_AUDIO,
                android.Manifest.permission.WRITE_SETTINGS,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void updateMainUI() {

        EinkProperty.setEinkFTTestAllResultPassed(FTUtils.isFTPassed());

        if (isPause) {
            return;
        }

//        if (FTUtils.isFactoryTestItemsAllPassedExcludeNoActivity()) {
        if (FactoryTestItemsEnum.aging.isPassed(mContext)) {

            txtDesc.setText(R.string.desc_after_aging);

            if (btnOtaTest != null) {
                btnOtaTest.setVisibility(View.GONE);
            }

        } else {

            txtDesc.setText(R.string.desc_before_aging);

        }

        final SpannableString msp = getSpannableString(FTUtils.getAgingResultInfo(mContext));
        txtAgingResult.setText(msp);

        updateItemByAfterAging();

    }


    @NonNull
    private SpannableString getSpannableString(String infoString) {
        final SpannableString msp = new SpannableString(infoString);
        String resultSearch = getString(R.string.ft_use_result_for_search);
        String pass = getString(R.string.test_result_pass);
        int index = infoString.indexOf(resultSearch);
        if (index > 0) {
            int len = index + resultSearch.length() + pass.length();
            if (len > infoString.length()) {
                len = infoString.length();
            }

            msp.setSpan(new RelativeSizeSpan(1.2f), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new UnderlineSpan(), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return msp;
    }

    private String getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum itemsEnum, boolean pass) {

        String result = itemsEnum.getResultForAfterAging(mContext);

        if (FTUtils.isFactoryTestItemsAllPassed() && itemsEnum.isKeepTestAfterAging()) {

            if (pass && !itemsEnum.isPassedForAfterAging(mContext)) {
                result = mContext.getString(R.string.test_result_pass);

                itemsEnum.setResultForAfterAging(mContext, result);

            }

            return result;
        }

        result = itemsEnum.getResult(mContext);

        if (pass && !itemsEnum.isPassed(mContext)) {
            result = mContext.getString(R.string.test_result_pass);

            itemsEnum.setResult(mContext, result);

            updateMainUI();
        }

        return result;

    }

    private void updateItemByAfterAging() {

        updateItemByAfterAging(false);
    }

    private void updateItemByAfterAging(boolean force) {

//        if (FTUtils.isFactoryTestItemsAllPassed() ) {
        if (FactoryTestItemsEnum.aging.isPassed(mContext)) {

            if (!myGridAdapter.isUseResultOfAfterAging() || force) {

                itemsEnumList.clear();

                myGridAdapter.setUseResultOfAfterAging(true);

                for (FactoryTestItemsEnum item : FactoryTestItemsEnum.values()) {
                    if (item == FactoryTestItemsEnum.bluetooth && !DeviceAttr.getRunningDeviceAttr().hasBluetooth()) {
                        continue;
                    }
                    if (item.isKeepTestAfterAging() && item.getItemClass() != null) {
                        itemsEnumList.add(item);
                    }
                }
            }

        } else {

            if (myGridAdapter.isUseResultOfAfterAging() || force) {
                itemsEnumList.clear();

                myGridAdapter.setUseResultOfAfterAging(false);

                for (FactoryTestItemsEnum item : FactoryTestItemsEnum.values()) {

                    if (item == FactoryTestItemsEnum.bluetooth && !DeviceAttr.getRunningDeviceAttr().hasBluetooth()) {
                        continue;
                    }
                    if (item.getItemClass() != null) {
                        itemsEnumList.add(item);
                    }
                }
            }
        }

        myGridAdapter.notifyDataSetChanged();

    }

    ///////////////////////////////////////////////////////////////

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        FactoryTestItemsEnum itemsEnum = myGridAdapter.getItem(position);
        if (itemsEnum == null || itemsEnum.getItemClass() == null) {
            return;
        }

        if (itemsEnum == FactoryTestItemsEnum.aging && (!FTUtils.isFactoryTestItemsAllPassedExcludeAging())) {
            Toast.makeText(mContext, R.string.aging_item_clicked_while_others_not_tested, Toast.LENGTH_SHORT).show();
            return;
        }

        Intent intent = new Intent(mContext, itemsEnum.getItemClass());
        startActivityForResult(intent, itemsEnum.getIdentify());

    }

    @Override
    public void onClick(View v) {

        if (v.getTag() instanceof Class) {
            startActivityUsingBtn((Class) v.getTag());
        }
    }

    private final static int REQUEST_CODE_USING_BTN = 1;

    private void startActivityUsingBtn(Class<?> cls) {
        Intent intent = new Intent(mContext, cls);
        startActivityForResult(intent, REQUEST_CODE_USING_BTN);
        DebugLog.e("start " + cls);
    }

    private class MyGridAdapter extends ArrayAdapter<FactoryTestItemsEnum> {

        private boolean useResultOfAfterAging = false;
        public MyGridAdapter(@NonNull Context context, int resource, @NonNull List<FactoryTestItemsEnum> objects) {
            super(context, resource, objects);
            useResultOfAfterAging = false;
        }

        public boolean isUseResultOfAfterAging() {
            return useResultOfAfterAging;
        }

        public void setUseResultOfAfterAging(boolean useResultOfAfterAging) {
            this.useResultOfAfterAging = useResultOfAfterAging;
        }

        @Override
        public View getView(final int position, @Nullable View convertView, @NonNull final ViewGroup parent) {

            ViewHolder holder = null;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            }

            if (holder == null) {
                holder = new ViewHolder();
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.item_test, null);
                holder.txtName = (TextView) convertView.findViewById(R.id.txtName);
                holder.txtStatus = (TextView) convertView.findViewById(R.id.txtStatus);
                convertView.setTag(holder);
            }

            final FactoryTestItemsEnum itemsEnum = getItem(position);

            if (itemsEnum != null) {
                holder.txtName.setText(itemsEnum.getNameResId());
                if (isUseResultOfAfterAging()) {
                    holder.txtStatus.setText(itemsEnum.getResultForAfterAging(getContext()));

                } else {
                    holder.txtStatus.setText(itemsEnum.getResult(getContext()));
                }
            }

            return convertView;
        }

    }

    private final class ViewHolder {
        TextView txtName;
        TextView txtStatus;
    }

    private BatteryInfo.OnBatteryChangedListener onBatteryChangedListener =
            new BatteryInfo.OnBatteryChangedListener() {
                @Override
                public void onBatteryChangedListener(BatteryInfo info) {

                    BatteryCurrentThresholdEnum thresholdEnum = null;
                    for (BatteryCurrentThresholdEnum e : BatteryCurrentThresholdEnum.values()) {
                        if (e.isInRange(info.getBatteryLevel())) {
                            thresholdEnum = e;
                            break;
                        }
                    }

                    boolean pass = (thresholdEnum != null &&
                            (info.getBatteryCurrent_mA() >= thresholdEnum.getCurrent() || info.getBatteryCurrent_mA() < 0));

                    String result = getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum.battery, pass);

                    String infoString = mContext.getString(R.string.ft_aging_battery_info,
                            info.getBatteryVoltage(),
                            info.getBatteryLevel(),
                            info.getBatteryStatusString(),
                            info.getBatteryCurrent_mA(), result);

                    SpannableString msp = getSpannableString(infoString);

                    txtBatteryInfo.setText(msp);

                }
            };


    ///////////////
    // sdcard start
    ///////////////
    private String getSDCardPath() {
        if (!isSDCardInserted()) {
            return "";
        }

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return "";
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList == null || volList.isEmpty()) {
            return "";
        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED)
                    && vol.getDescription(mContext).contains("SD")) {

                try {
                    Method getPath = StorageVolume.class.getMethod("getPath");
                    String path = (String) getPath.invoke(vol);
                    DebugLog.i( "StoragePath--->" + path);

                    return path;
//
//                    StatFs stat = new StatFs(path);
//
//                    Log.e(TAG, "total size = " + Formatter.formatFileSize(this, stat.getTotalBytes()));
//                    Log.e(TAG, "free size = " + Formatter.formatFileSize(this, stat.getFreeBytes()));

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

        return "";

    }
    private boolean isSDCardInserted() {

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return false;
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList == null || volList.isEmpty()) {
            return false;
        }

        for (StorageVolume vol : volList) {

            DebugLog.i("vol state = " + vol.getState() + ", desc = " + vol.getDescription(mContext));

        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED)
                    && vol.getDescription(mContext).contains("SD")) {

                return true;
            }
        }

        return false;

    }

    private void updateUIWhileSDCardMounted() {

        txtSdcardInfo.setText(R.string.sdcard_test_ejected);
        if (!isSDCardInserted()) {
            return;
        }

        String path = getSDCardPath();
        if (TextUtils.isEmpty(path)) {
            return;
        }

        StatFs stat = new StatFs(path);

        String result = getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum.sdcard, true);

        String infoString = mContext.getString(R.string.sdcard_test_inserted_info,
                Formatter.formatFileSize(mContext, stat.getTotalBytes()),
                Formatter.formatFileSize(mContext, stat.getFreeBytes()),
                result);

        SpannableString msp = getSpannableString(infoString);

        txtSdcardInfo.setText(msp);

    }

    private IntentFilter getIntentFilterOfSDCard() {
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);
        intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);

        intentFilter.addDataScheme("file");

        return intentFilter;
    }

    private void registerSdcardReceiver() {
        if (!DeviceAttr.getRunningDeviceAttr().hasTFCard()) {
            return;
        }

        mContext.registerReceiver(sdcardReceiver, getIntentFilterOfSDCard());

    }

    private void unregisterSdcardReceiver() {
        if (!DeviceAttr.getRunningDeviceAttr().hasTFCard()) {
            return;
        }
        mContext.unregisterReceiver(sdcardReceiver);
    }


    private final BroadcastReceiver sdcardReceiver =  new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }
            DebugLog.e( "sdcard action = " + action + ", intent.getData() = " + intent.getData());

            updateUIWhileSDCardMounted();

        }
    };

    ///////////////
    // sdcard end
    ///////////////

    private void startLedCtrl() {
        myHandler.sendEmptyMessage(MyHandler.MSG_LED_CTRL);
    }
    private void stopLedCtrl() {
        myHandler.removeMessages(MyHandler.MSG_LED_CTRL);
        LedCtrl.setLed(false, LedCtrl.LedAttr.led_green, LedCtrl.LedAttr.led_red);
    }

    private static final class MyHandler extends Handler {

        private final WeakReference<MainActivity> reference;

        private final static int MSG_LED_CTRL = 1000;
        private final static int PERIOD_LED_CTRL = 2000;//2s

        private final static int MSG_CHECK_AGING = 2000;
        private final static int DELAY_CHECK_AGING = 2000;//1s

        private int ledOnCount = 0;

        public MyHandler(MainActivity activity) {
            reference = new WeakReference<MainActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = reference.get();
            if (activity == null) {
                return;
            }
            switch (msg.what) {
                case MSG_CHECK_AGING:
                    activity.checkIfStartAging();
                    break;
                case MSG_LED_CTRL:

                    if (activity.batteryInfo.getBatteryLevel() >= HtfyunBuildConfig.STOP_LED_BATTERY_LEVEL) {
                        LedCtrl.setLed(true, LedCtrl.LedAttr.led_green);
                        break;
                    }

                    if (++ledOnCount > 10000) {
                        ledOnCount = 0;
                    }
                    LedCtrl.setLed((0 == (ledOnCount % 2)), LedCtrl.LedAttr.led_green);
                    LedCtrl.setLed(!(0 == (ledOnCount % 2)), LedCtrl.LedAttr.led_red);

                    sendEmptyMessageDelayed(msg.what, PERIOD_LED_CTRL);

                    break;
            }

        }
    }
}
